home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 7
/
FM Towns Free Software Collection 7.iso
/
data
/
happysrc
/
paasm.c
< prev
next >
Wrap
Text File
|
1993-11-30
|
27KB
|
773 lines
/**********************************************************************
*
* *** HAPPy Pascal Compiler ***
* P-code assmebler
*
* Copyright (c) H.Asano 1992,1993
*
**********************************************************************/
#define EXTERN extern
#define Maxlabel 1800 /* 最大ラベル数 */
#include <float.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "version.h"
#include "hapai.h"
/********* co-operation table **********/
static char cop[] =
{
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 */
/* 0x */ 115, 105, 70, 75, 0, 0, 80, 0, 0, 85,
/* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 2x */ 0, 0, 0, 0, 0, 0, 95, 0, 0, 0,
/* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
} ;
/***************************************/
/* P-code 標準手続き・関数ニーモニック表*/
/***************************************/
static char sptable[][4] =
{
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 */
/* 0x */ "get","put","rst","rln","new","wln","wrs","wrb","wri","wrr",
/* 1x */ "wrc","rdi","rdr","rdc","sin","cos","exp","log","sqt","atn",
/* 2x */ "pge","eof","eol","dis","wrf","rwt","trs","trw","tgt","tpt"
} ;
/***************************************/
/* ラベル表 */
/***************************************/
enum lbst { entered, /* ラベル未登録の状態 */
defined /* ラベル定義済の状態 */
};
static struct {
int val ; /* value */
enum lbst st ; /* status {enterd,defined} */
} labeltab[Maxlabel] ;
/***************************************/
/* 仮想計算機 記憶装置 */
/***************************************/
static _store store[Maxstore] ;
/***************************************/
/* 変数定義 */
/***************************************/
static char *PcodeSourceName; /* P-codeソースファイル名 */
static char *CompVersion ; /* コンパイラのバージョン */
static FILE *pcsfile ; /* P-codeソースファイルポインタ */
static FILE *objfile ; /* P-codeオブジェクトファイルポインタ */
static int codesize ; /* コードのワードサイズ */
static int objsize ; /* オブジェクト全体のワードサイズ */
static int labelvalue ; /* labelの値 */
static char ch ; /* 読込文字 */
static int intch ; /* 読込処理内での読込文字 */
static int pc ; /* program counter */
static char op ; /* P-code operation */
static char p ; /* P-code p operand */
static int q ; /* P-code q operand */
static int start = -1 ; /* オブジェクト開始の合図 */
/*********************************************************************/
/***************************************/
/* エラーメッセージ出力処理 */
/***************************************/
static void paerr(int errno)
{
static struct _errmsg {
int msgno ; /* error message number */
char *errmsg ; /* error message */
} errtb[] = {
{1, "命令数が多すぎてアセンブルできない"},
{2, "オブジェクトファイルがオープンできない"},
{3, "オブジェクトファイル書き込みでエラーが発生した"},
{4, "ラベル数が多すぎてアセンブルできない"},
{5, "定数を格納するメモリを使い果たしてアセンブルできない"},
{6, "P-codeソースファイルがオープンできない"},
{7, "PC.EXEとPA.OVLのバージョンが違う"}
} ;
int i = -1 ;
while(errtb[++i].msgno != errno) ; /* search message */
fprintf(stderr,"A%03d: %s\n", errno, errtb[i].errmsg);
exit(3) ; /* アセンブルエラーで停止 */
}
/***************************************/
/* reset() : reset関数 */
/***************************************/
static void reset(char *filename)
{
pcsfile = fopen(filename,"r") ;
if(pcsfile == NULL) paerr(6) ;
intch = getc(pcsfile) ; /* 1文字先読み */
}
/***************************************/
/* eoln() : eolnマクロ定義 */
/***************************************/
#define eoln() (intch == '\n') /* 改行を読んでいれば真 */
/***************************************/
/* readc() : char型read処理 */
/***************************************/
static char readc(void)
{
int oldch ;
oldch = intch ;
intch = getc(pcsfile) ;
return((char)oldch) ;
}
/***************************************/
/* readi() : integer型入力処理 */
/***************************************/
static integer readi(void)
{
integer ival = 0 ;
int sign = 1 ;
if(intch == ' ')
while((intch = getc(pcsfile)) == ' '); /* 空白読み飛ばし */
if((intch=='+') || (intch=='-')) { /* 符号の時 */
sign = (intch=='+') ? 1 : -1 ; /* 符号に応じた正負 */
intch = getc(pcsfile) ;
}
do {
intch -= '0' ;
ival = ival*10 + intch ;
if(eoln()) break ; /* EOLNならばそこまで */
intch=getc(pcsfile) ;
} while(('0' <= intch) && (intch <= '9')) ;
return(sign*ival) ;
}
/***************************************/
/* readr() : real型入力処理 */
/***************************************/
static float readr(void)
{
char buf[20] ;
int i = 0 ;
while(intch == ' ') intch = getc(pcsfile) ; /* 空白読み飛ばし */
do {
buf[i++] = (char)intch ;
intch = getc(pcsfile) ;
} while (intch != '\n') ;
buf[i] = '\0' ;
return((float)atof(buf)) ; /* 浮動小数点へ変換 */
}
/***************************************/
/* readln() : EOLまで読み飛ばす処理 */
/***************************************/
static void readln(void)
{
while(!eoln()) intch = getc(pcsfile) ;
intch = getc(pcsfile);
}
/***************************************/
/* オブジェクトファイル書出処理 */
/***************************************/
static void putobject(char *area, int size)
{
fwrite(area,size,1,objfile) ;
if(ferror(objfile)) paerr(3) ; /* 書き込み失敗 */
}
/***************************************/
/* 初期設定処理 */
/***************************************/
static void init(void)
{
int i;
_fpreset() ; /* 浮動小数点パッケージ初期設定*/
for(i=0;i<Maxlabel;i++) { /* ラベル表 の 初期設定 */
labeltab[i].val = -1 ;
labeltab[i].st = entered;
}
reset(PcodeSourceName) ; /* P-codeソースファイルのオープン */
objfile = fopen("pcode.pco","wb") ;/* ファイルオープン */
if(objfile == NULL) paerr(2) ; /* オープンできない */
if(codesize > Maxstore) /* 記憶装置の大きさより大きい時*/
paerr(1) ; /* プログラム停止 */
if(strcmp(CompVersion,version))
paerr(7) ; /* バージョン不一致 */
putobject(version,strlen(version)+1) ; /* バージョン番号書出 */
objsize = codesize ;
}
/***************************************/
/* ラベル表登録処理 */
/***************************************/
static void update(int x)
{ /* x: label名 */
int curr,succ ;
if(x > Maxlabel-1) paerr(4) ; /* ラベル数が多すぎる */
if(labeltab[x].val != -1) { /* 前方参照されている時 */
curr = labeltab[x].val;
for(;;) {
succ = store[curr].vo.cdq;
store[curr].vo.cdq = labelvalue;
if(succ == -1) break; /* 終了 */
else curr = succ;
}
}
labeltab[x].st = defined ;
labeltab[x].val = labelvalue ;
}
/***************************************/
/* ラベル値決定処理 */
/***************************************/
static void lookup(int x)
{
if(labeltab[x].st == entered) { /* 未定義 */
q = labeltab[x].val ; /* 初期値のまま -1 */
labeltab[x].val = pc ; /* 今のpcを格納 */
}
else q = labeltab[x].val ; /* 定義済の時 */
}
/***************************************/
/* ラベル値読込処理 */
/***************************************/
static void labelsearch(void)
{
while(ch != 'L') /* 'L' まで 読み飛ばし */
ch = readc() ;
lookup((int)readi()); /* labelを読み 値を探す */
}
/********* typesymbol() : instruction名4文字目によってopを決定する *********/
static void typesymbol(void)
{
int i;
switch(ch) {
case 'i' : return ; /* 'i' の時は opはそのまま */
case 'a' : i=0; break;
case 'r' : i=1; break;
case 's' : i=2; break;
case 'b' : i=3; break;
case 'c' : i=4;
}
op=cop[op]+i; /* opの変更 */
}
/**************************************/
/* PTN0() : オペランドのない命令 */
/**************************************/
static void PTN0(void)
{
}
/**************************************/
/* PTN1() : lod,strのアセンブル */
/**************************************/
static void PTN1(void)
{
typesymbol() ;
p=(char)readi() ;
q=(int)readi() ;
}
/**************************************/
/* PTN2() : lda,movのアセンブル */
/**************************************/
static void PTN2(void)
{
p=(char)readi() ;
q=(int)readi() ;
}
/***************************************/
/* PTN3() : mst,cui,bas,traのアセンブル*/
/***************************************/
static void PTN3(void)
{
p=(char)readi() ;
}
/**************************************/
/* PTN4() : cup,ent,ejpのアセンブル */
/**************************************/
static void PTN4(void)
{
p=(char)readi() ;
labelsearch();
}
/************************************************/
/* PTN5() : equ,neq,geq,grt,leq,lesのアセンブル */
/************************************************/
static void PTN5(void)
{
switch(ch) {
case 'a' : ; break ;
case 'i' : p=1 ; break ;
case 'r' : p=2 ; break ;
case 'b' : p=3 ; break ;
case 's' : p=4 ; break ;
case 'c' : p=6 ; break ;
case 'm' : p=5 ;
q=(int)readi() ;
}
}
/**************************************/
/* PTN6() : ldo,sroのアセンブル */
/**************************************/
static void PTN6(void)
{
typesymbol() ;
q=(int)readi();
}
/**************************************/
/* PTN7() : inc,decのアセンブル */
/**************************************/
static void PTN7(void)
{
switch(ch) {
case 'a' :/*p=0*;*/ break ;
case 'i' : p=1; break ;
case 'r' : p=2; break ;
case 'b' : p=3; break ;
case 'c' : p=6; break ;
}
q = (int)readi() ;
}
/****************************************/
/* PTN8() : ujp,fjp,xjp,lapのアセンブル */
/****************************************/
static void PTN8(void)
{
labelsearch() ;
}
/**************************************/
/* CHK() : chkのアセンブル */
/**************************************/
static void CHK(void)
{
integer lb,ub ;
typesymbol() ;
p = (char)readi() ; /* チェック種別 */
lb = readi(); /* 下限値 */
ub = readi(); /* 上限値 */
store[objsize ].vi = lb ;
store[objsize+1].vi = ub ;
q=codesize;
do {
q++ ;
} while((store[q-1].vi != lb) || (store[q].vi != ub)) ;
if(q == objsize) objsize++ ; /* 最後に1つだけ定数追加の時 */
if(q-1 == objsize) objsize += 2 ; /* 最後に2つの 対数追加の時 */
if(objsize>=Maxstore) paerr(5) ; /* 定数格納不可 */
}
/**************************************/
/* CSP() : cspのアセンブル */
/**************************************/
static void CSP(void)
{
char name[4];
do ;
while((ch=readc())==' ') ; /* 空白を読み飛ばし */
*name = ch ; /* 1文字目 */
*(name+1) = readc() ; /* 2文字目 */
*(name+2) = readc() ; /* 3文字目 */
*(name+3) = '\0' ;
while(strcmp(sptable[q],name) != 0)/*対応のqをサーチ */
q++ ;
}
/**************************************/
/* IND() : indのアセンブル */
/**************************************/
static void IND(void)
{
typesymbol() ;
q=(int)readi() ;
}
/**************************************/
/* IXA() : ixaのアセンブル */
/**************************************/
static void IXA(void)
{
integer lb,ub ;
lb = readi() ; /* 下限値 */
ub = readi() ; /* ixa値 */
store[objsize ].vi = lb ;
store[objsize+1].vi = ub ;
q=codesize;
do {
q++ ;
} while((store[q-1].vi != lb) || (store[q].vi != ub)) ;
if(q == objsize) objsize++ ; /* 最後に1つだけ定数追加の時 */
if(q-1 == objsize) objsize += 2 ; /* 最後に2つの 対数追加の時 */
if(objsize>=Maxstore) paerr(5) ; /* 定数格納不可 */
}
/**************************************/
/* LAO() : laoのアセンブル */
/**************************************/
static void LAO(void)
{
q=(int)readi();
}
/**************************************/
/* LCA() : lcaのアセンブル */
/**************************************/
static void LCA(void)
{
q=objsize;
readc() ; /* "を読み飛ばす */
ch=readc() ; /* "の次の文字 */
while(ch != '\"') {
store[objsize++].vc = (unsigned char)ch ;
if(objsize>=Maxstore)
paerr(5) ; /* 定数格納不可 */
ch=readc() ; /* 次の文字 */
}
}
/**************************************/
/* LDC() : ldcのアセンブル */
/**************************************/
static void LDC(void)
{
integer lnumber ;
float rnumber ;
long s,s1 ;
switch(ch) {
case 'i' : p=1 ; /* integer type */
lnumber = readi() ;
if(labs(lnumber) < (long)Largeint)
q = (int)lnumber;
else { /* 大きな数の時 */
op = 66 ; /* lci命令に変更 */
store[objsize].vi = lnumber ;
q=codesize-1;
do ;
while(store[++q].vi != lnumber) ;
if(q == objsize) {
objsize++ ;
if(objsize>=Maxstore)
paerr(5) ; /* 定数格納不可 */
}
}
break ;
case 'c' : p=6 ; /* char type */
while((ch=readc())==' ') ;
q=readc() ;
break ;
case 'b' : p=3; /* boolean */
q=(int)readi() ;
break;
case 'n' : p=0 ; /* ldc nil */
q=0 ;
break ;
case 's' : p = 4; /* set type */
s=0;
while(readc() != '(') ;
ch=readc() ;
while(ch!=')') {
s1=(int)readi() ;
addset(s,s1) ;
ch=readc() ;
}
store[objsize].vs = s ;
q = codesize ;
while(store[q].vs != s) q++ ;
if(q==objsize) {
objsize++ ;
if(objsize>=Maxstore)
paerr(5) ; /* 定数格納不可 */
}
break ;
case 'r' : p = 2 ;
rnumber = readr() ;
store[objsize].vr = rnumber ;
lnumber = store[objsize].vi ;
/* 浮動小数点の形で比較を行うと思わぬ落とし穴があるので
ビット列の比較をするために、union型のviから数を得る*/
q=codesize-1;
do ;
while(store[++q].vi != lnumber) ;
if(q == objsize) {
objsize++ ;
if(objsize>=Maxstore)
paerr(5) ; /* 定数格納不可 */
}
break ;
}
}
/**************************************/
/* ORD() : ordのアセンブル */
/**************************************/
static void ORD(void)
{
switch(ch) {
case 'b' : p=3 ; break ;
case 'c' : p=6 ;
}
}
/**************************************/
/* RET() : retのアセンブル */
/**************************************/
static void RET(void)
{
switch(ch) {
case 'p' : ; break ;
case 'i' : p=1 ; break ;
case 'r' : p=2 ; break ;
case 'c' : p=3 ; break ;
case 'b' : p=4 ; break ;
case 'a' : p=5 ; break ;
}
}
/**************************************/
/* STO() : stoのアセンブル */
/**************************************/
static void STO(void)
{
typesymbol() ;
}
/**********************************************************************/
/* P-code ニーモニック表 */
/**********************************************************************/
static char instr[][4] =
{
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 */
/* 0x */ "lod","ldo","str","sro","lda","lao","sto","ldc","bas","ind",
/* 1x */ "inc","mst","cup","ent","ret","csp","ixa","equ","neq","geq",
/* 2x */ "grt","leq","les","ujp","fjp","xjp","chk","lap","adi","adr",
/* 3x */ "sbi","sbr","sgs","flt","flo","trc","ngi","ngr","sqi","sqr",
/* 4x */ "abi","abr","not","and","ior","dif","int","uni","inn","mod",
/* 5x */ "odd","mpi","mpr","dvi","dvr","mov","lca","dec","stp","ord",
/* 6x */ "chr","ujc","mms","msi","cui","ejp","...","cka","tra","rou"
} ; /* ↑ ここはlci */
/******* ニーモニック対応のエントリ表 ********/
static struct entry {
void (*func)(void) ;
} OP[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 */
/* 0x */ PTN1, PTN6 ,PTN2, PTN6, PTN2, LAO , STO , LDC , PTN3, IND ,
/* 1x */ PTN7, PTN3, PTN4, PTN4, RET , CSP , IXA , PTN5, PTN5, PTN5,
/* 2x */ PTN5, PTN5, PTN5, PTN8, PTN8, PTN8, CHK , PTN8, PTN0, PTN0,
/* 3x */ PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0,
/* 4x */ PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0,
/* 5x */ PTN0, PTN0, PTN0, PTN0, PTN0, PTN2, LCA , PTN7, PTN0, ORD ,
/* 6x */ PTN0, PTN0, PTN0, PTN0, PTN3, PTN4, PTN0, PTN0, PTN3, PTN0
} ;
/***************************************/
/* 1行アセンブル処理 */
/***************************************/
static void assemble(void)
{
char name[4];
*name = ch ; /* 1文字目 */
*(name+1) = readc() ; /* 2文字目 */
*(name+2) = readc() ; /* 3文字目 */
*(name+3) = '\0' ;
if(!eoln()) ch=readc();
/* そこで行が終わってなければ次の文字を読む */
op = -1 ;
while(strcmp(instr[++op],name)) ; /* instructionよりopを決定 */
/* このようなリニアサーチはスピードが遅いので改良しよう */
p = 0 ;
q = 0 ;
OP[op].func() ; /* opに対応したアセンブル */
store[pc ].vo.cdop = op; /* code table へ 格納 */
store[pc ].vo.cdp = p ;
store[pc++].vo.cdq = q ;
}
/********** generate() : 行の最初に呼ばれる処理 **********/
static void generate(void)
{
int x ; /* label値 */
int i ; /* 作業カウンタ */
char progname[33] ; /* プログラム名 */
char filename[33] ; /* ファイル名 */
int fileadr ; /* ファイルアトレス */
int filesize ; /* バッファ変数の大きさ */
for(;;) {
ch=readc(); /* 行の最初の文字を読む */
switch(ch) {
case 'Q' : return ; /* アセンブル終わり */
case 'N' : /* プログラム名 */
readc() ; /* 空白を読み飛ばす */
i=0 ;
while(!eoln()) /* プログラム名取得 */
progname[i++] = readc() ;
progname[i] = '\0' ;
putobject(progname,i+1) ; /* 書出 */
break ;
case 'F' : /* ファイルアドレス */
readc() ; /* 空白を読み飛ばす */
i=0 ;
while((ch=readc()) != ' ') /* ファイル名取得 */
filename[i++] = ch ;
filename[i] = '\0' ;
readc() ; /* 空白を読み飛ばす*/
fileadr = (int)readi() ; /* ファイルアトレス */
putobject((char*)&fileadr,sizeof(fileadr));/* 書出 */
filesize = (int)readi(); /* バッファサイズ */
putobject((char*)&filesize,sizeof(filesize));/* 書出*/
putobject(filename,i+1) ; /* ファイル名書出 */
break ;
case ';' : /* 注釈行を無視 */
break ;
case 'L' : x=(int)readi(); /* label名を読む */
if(!eoln()) ch=readc() ;
if(ch=='=') labelvalue=(int)readi();
/* label値がある時 */
else labelvalue=pc; /* ない時はpcの値 */
update(x); /* label登録 */
break ;
case ' ' : ch=readc(); /* 空白の時は その行をアセンブル */
assemble();
default : ;
}
readln() ;
}
}
/*****************************************/
/* assemblelist() : アセンブルリスト出力 */
/*****************************************/
static void assemblelist(void)
{
reset(PcodeSourceName) ; /* P-codeソースファイルのオープン */
printf("\n ADDR OP P Q P-code source statement\n");
printf( "================================================\n");
pc = 0 ;
for(;;) {
ch=readc(); /* 行の最初の文字 */
switch(ch) {
case 'N' :
case 'F' :
case 'Q' :
case ';' :
case 'L' : printf(" %c",ch);
while(!eoln()) printf("%c",readc());
printf("\n");
readln();
if(ch=='Q') {
if(codesize != objsize)
printf(" %4d:\n ~: constant data\n %4d:\n",
codesize,objsize-1) ;
fclose(pcsfile) ; /* ソースファイルのクローズ */
return;
}
break;
case ' ' : printf(" %4d: %3d %3d %6d",
pc, store[pc].vo.cdop, store[pc].vo.cdp ,
store[pc].vo.cdq);
pc++;
printf(" %c",ch);
while(!eoln()) printf("%c",readc());
printf("\n");
readln();
break;
}
}
}
/***************************************/
/* main() : P-codeアセンブラメイン処理 */
/***************************************/
int main(int argc,char *argv[])
{
codesize = atoi(argv[1]) ; /* 命令コードの数 */
PcodeSourceName = argv[2] ; /* P-codeソースファイル名 */
CompVersion = argv[3] ; /* コンパイラのバージョン */
init(); /* 各種初期設定 */
generate(); /* アセンブル */
fclose(pcsfile) ; /* ソースファイルのクローズ */
for(pc=0;pc<codesize;pc++) { /* qオペランドの補正処理 */
op = store[pc].vo.cdop ;
if((/*lao*/ op == 5) || (/*ldox*/ op == 1 || (105<=op && op<=109) )
|| (/*srox*/ op == 3 || (75<=op && op<=79) ) )
store[pc].vo.cdq += objsize ;
}
putobject((char*)&start,sizeof(start)) ; /* オブジェクト開始合図 */
putobject((char*)store,objsize*sizeof(_store)) ; /* オブジェクト出力*/
if(fflush(objfile) == EOF) paerr(3) ;
if(fclose(objfile) == EOF) paerr(3) ;
/* クローズできなければ書き込み失敗の可能性がある */
fputs( " *** Assemble completed. ***\n",stderr);
fprintf(stderr," *** code = %5d words constant data = %5d words ***\n",
codesize, objsize-codesize);
if(argc==5) assemblelist(); /* アセンブルリストの出力 */
return(0) ; /* 正常終了 */
}